package cn.yqx.bankshop.oauth2.handle;

import cn.yqx.bankshop.oauth2.service.impl.CustomUserDetailsService;
import cn.yqx.bankshop.result.Result;
import cn.yqx.bankshop.result.ResultCode;
import cn.yqx.bankshop.user.pojo.LoginShopUser;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Lu
 * @desc 自定义登录成功处理类
 */
@Component
@Slf4j
public class CustomAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
    @Autowired
    CustomUserDetailsService customUserDetailsService;
    @Autowired
    ClientDetailsService clientDetailsService ;
    @Autowired
    private AuthorizationServerTokenServices authorizationServerTokenServices;
    @Autowired
    UserDetailsService userDetailsService ;

    private static final String GRAND_TYPE = "password" ;
    private static final String USERNAME_STR = "username" ;
    private static final String USERID_STR = "userid" ;
    private static final String ROLE_TYPE = "roleType" ;
    private static final String PASSWORD_STR = "password" ;
    private static final String DEFAULT_CLIENT_ID = "bankshop-web" ;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {

        String clientId =  request.getParameter("client_id") == null ? DEFAULT_CLIENT_ID : request.getParameter("client_id") ;
        try{
            response.setContentType("application/json;charset=UTF-8");
            ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);

            Map<String, String> params = new HashMap<String, String>();
            params.put(USERNAME_STR, authentication.getName());
            UserDetails userDetails = userDetailsService.loadUserByUsername(authentication.getName()) ;
            params.put(PASSWORD_STR, userDetails.getPassword());

            TokenRequest tokenRequest = new TokenRequest(params, clientId, clientDetails.getScope(), GRAND_TYPE);
            OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
            OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
            OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
            JSONObject json = new JSONObject() ;

            //添加用户名
            json.put(USERNAME_STR,authentication.getName());
            LoginShopUser loginShopUser = (LoginShopUser)userDetails ;
            json.put(USERID_STR,loginShopUser.getId()) ;
            json.put(ROLE_TYPE,loginShopUser.getRoleType()) ;
            //添加角色名
            response.getWriter().write(JSON.toJSONString(token2Json(token,json)));

        }catch (Exception e){
            Result result = Result.failed(ResultCode.TOKEN_CLIENT_ERROR) ;
            response.getWriter().write(JSON.toJSONString(result));
        }
    }


    private Object token2Json(OAuth2AccessToken token,JSONObject json) {

        Result result = Result.success();
        json.put("access_token", token.getValue());
        json.put("token_type", token.getTokenType());
        json.put("refresh_token", token.getRefreshToken().getValue());
        json.put("expires_in", token.getExpiresIn());
        json.put("scope", token.getScope());
        result.setData(json);

        Map<String, Object> map = token.getAdditionalInformation();
        json.putAll(map);

        return result;
    }

}
